﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace 桌面视频录制
{
    [Serializable]
  　public class DrawArc : DrawObject
    {
       protected Point leftUpPoint;
       protected Point startPoint;
       protected Point sizeControlPoint;
       protected Point rotateControlPoint;
       protected Point angleControlPoint;
       //protected float angle = 0.0f;//弧度表示
       protected int width;
       protected int height;
       protected int selectedIndex;
       protected double slope;//矩形左侧边的斜率
       protected float sweepAngle;
       protected float startAngle;
       protected Point rotatePoint;
       protected Point sweepPoint;
       public DrawArc(Point startPoint)
       {
           this.startPoint = startPoint;
           this.width = 1;
           this.height = 1;
           this.startAngle = 0.0f;
           this.sweepAngle = (float)(Math.PI / 2);
       }
       public override void Draw(Graphics g)
       {
           if (width < 1 || height < 1)
               return;
           Pen pen = new Pen(this.PenColor, this.PenWidth);
           g.DrawArc(pen, leftUpPoint.X, leftUpPoint.Y, width, height, (float)(startAngle * 180 / Math.PI), (float)(sweepAngle * 180 / Math.PI));
           pen.Dispose();
       }
       public override void DrawControlPoint(Graphics g)
       {
           StaticFunction.DrawControlRegion(g, startPoint);
           StaticFunction.DrawControlRegion(g, rotateControlPoint);
           StaticFunction.DrawControlRegion(g, angleControlPoint);

           Pen pen = new Pen(Color.Red);
           AdjustableArrowCap arrow = new AdjustableArrowCap(2, 2, true);
           pen.CustomEndCap = arrow;
           pen.CustomStartCap = arrow;
           g.DrawArc(pen, rotateControlPoint.X - 7, rotateControlPoint.Y - 7, 15, 15, -120, 180);
           pen.Dispose();
           pen = null;
       }
       public override void MouseMove(System.Windows.Forms.MouseEventArgs e)
       {
           this.sizeControlPoint = e.Location;
           this.width = 2 * (e.X - startPoint.X);
           this.height = 2 * (e.Y - startPoint.Y);
           this.rotateControlPoint.X = e.X;
           this.rotateControlPoint.Y = startPoint.Y;
           this.angleControlPoint.X = startPoint.X;
           this.angleControlPoint.Y = e.Y;
           this.leftUpPoint.X = 2 * startPoint.X - sizeControlPoint.X;
           this.leftUpPoint.Y = 2 * startPoint.Y - sizeControlPoint.Y;
       }
       public override bool JudgeIsSelected(System.Windows.Forms.MouseEventArgs e)
       {
           GraphicsPath path = new GraphicsPath();
           path.AddPolygon(new Point[] { startPoint, rotateControlPoint, angleControlPoint });
           Region region = new Region(path);
           if (region.IsVisible(e.Location))
           {
               path.Dispose();
               region.Dispose();
               return true;
           }
           else
           {
               path.Dispose();
               region.Dispose();
               return false;
           }
       }
       public override void MoveLocation(System.Windows.Forms.MouseEventArgs e)
       {
           int dx = e.X - this.MouseDownPoint.X;
           int dy = e.Y - this.MouseDownPoint.Y;
           this.MouseDownPoint = e.Location;

           this.startPoint = new Point(startPoint.X + dx, startPoint.Y + dy);
           sizeControlPoint = new Point(sizeControlPoint.X + dx, sizeControlPoint.Y + dy);
           rotateControlPoint = new Point(rotateControlPoint.X + dx, rotateControlPoint.Y + dy);
           angleControlPoint = new Point(angleControlPoint.X + dx, angleControlPoint.Y + dy);
           this.leftUpPoint = new Point(leftUpPoint.X + dx, leftUpPoint.Y + dy);
       }
       public override bool JudgeIsInControlRegion(System.Windows.Forms.MouseEventArgs e)
       {
           Rectangle rect = StaticFunction.GetControlRect(startPoint);
           if (rect.Contains(e.Location))
           {
               selectedIndex = 0;
               return true;
           }
           rect = StaticFunction.GetControlRect(rotateControlPoint);
           if (rect.Contains(e.Location))
           {
               selectedIndex = 1;
               return true;
           }
           rect = StaticFunction.GetControlRect(angleControlPoint);
           if (rect.Contains(e.Location))
           {
               selectedIndex = 3;
               return true;
           }
           return false;
       }
       private Point GetChangeSizePoint(double k, Point relativePoint, MouseEventArgs e)
       {
           double x = (relativePoint.Y - e.Y + k * e.X + 1.0 * relativePoint.X / k) * k / (k * k + 1);
           int y = (int)(k * (x - e.X) + e.Y);
           return (new Point((int)x, y));
       }
       private Point GetRotatePoint(int radius, Point centerPoint, float angle)
       {
           int x = centerPoint.X + (int)(radius * Math.Cos(angle));
           int y = centerPoint.Y + (int)(radius * Math.Sin(angle));
           return (new Point(x, y));
       }
       public override void ChangeSize(System.Windows.Forms.MouseEventArgs e)
       {
           if (selectedIndex == 0)
           {
               int dx = e.X - this.MouseDownPoint.X;
               int dy = e.Y - this.MouseDownPoint.Y;
               this.MouseDownPoint = e.Location;
               startPoint = e.Location;
               this.leftUpPoint.X = 2 * e.X - sizeControlPoint.X;
               this.leftUpPoint.Y = 2 * e.Y - sizeControlPoint.Y;
               width = 2 * (e.X - leftUpPoint.X);
               height = 2 * (e.Y - leftUpPoint.Y);
               this.angleControlPoint = GetRotatePoint(height / 2, startPoint, startAngle + sweepAngle);
               this.rotateControlPoint = GetRotatePoint(width / 2, startPoint, startAngle);
           }
           else if (selectedIndex == 1)
           {
               float includedAngle = (float)(Math.Atan(1.0 * height / width));//矩形对角线与横边的夹角
               this.startAngle = (float)(Math.Atan2(e.Y - startPoint.Y, e.X - startPoint.X));//直线斜率对应的角度 
               rotateControlPoint = GetRotatePoint(width / 2, startPoint, startAngle);
               angleControlPoint = GetRotatePoint(height / 2, startPoint, startAngle + sweepAngle);
               //计算旋转后左侧边的斜率
               if (startPoint.X != angleControlPoint.X)
                   this.slope = 1.0 * (startPoint.Y - angleControlPoint.Y) / (startPoint.X - angleControlPoint.X);
           }
           else if (selectedIndex == 3)
           {
               float angle = (float)(Math.Atan2(e.Y - startPoint.Y, e.X - startPoint.X));//直线斜率对应的角度 
               this.sweepAngle = angle - this.startAngle;
               sweepPoint = e.Location;
               angleControlPoint = GetRotatePoint(height / 2, startPoint, angle);//GetPointOnEllipse(GetRotatePoint(height / 2, startPoint, angle));
           }
       }
       //出现溢出错误
       //private Point GetPointOnEllipse(Point p)
       //{
       //    double k = 1.0 * (p.Y - startPoint.Y) / (p.X - startPoint.X);
       //    double a = 1.0 * this.width / 2;
       //    double b = 1.0 * this.height / 2;
       //    double A = b * b + a * a * k * k;
       //    double B = 2 * k * a * a * (startPoint.Y - k * startPoint.X);
       //    double C = a * a * (startPoint.Y - k * startPoint.X) * (startPoint.Y - k * startPoint.X) - a * a * b * b;
       //    int x = (int)((-B + Math.Sqrt(B * B - 4 * A * C)) / 2 * A);
       //    int y = (int)(k * (x - startPoint.X) + startPoint.Y);
       //    return new Point(x, y);
       //}
       public override bool IsAllInRectangle(Region region)
       {
           return (region.IsVisible(startPoint) && region.IsVisible(rotateControlPoint) && region.IsVisible(angleControlPoint));
       }
       public override string ToString()
       {
           string printMsg = "[弧线(" + this.startPoint.X + "," + this.startPoint.Y + ")]->[ID:" + this.Id + "]";
           return printMsg;
       }
       public override string GetDrawObjectMsg()
       {
           string drawObjectMsg = "弧线->起始位置(" + this.startPoint.X + "," + this.startPoint.Y + "),宽高(" + (this.width / 2) + "," + (this.height / 2) + "),起始角度:" + ((int)(startAngle * 180 / Math.PI)) + "°,偏移角度:" + ((int)(sweepAngle * 180 / Math.PI)) + "°";
           return drawObjectMsg;
       }
       public override Point[] GetPoints()
       {
           int x = rotateControlPoint.X + angleControlPoint.X - startPoint.X;
           int y = rotateControlPoint.Y + angleControlPoint.Y - startPoint.Y;
           return new Point[] { startPoint, rotateControlPoint, new Point(x, y), angleControlPoint };
       }
       public override Rectangle GetRectangle()
       {
           return new Rectangle();
       }
       public override DrawObject Clone(Point point)
       {
           return new DrawArc(point);
       }
       public override Point[] GetTextBoxLocation()
       {
           return new Point[] { startPoint, sizeControlPoint };
       }
    }
}
